package com.snts.synchronization.core;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Random;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class TimeStampWithTimeZone {

	private static final Log log = LogFactory.getLog(TimeStampWithTimeZone.class);

	private short year;
	private short month;
	private short day;
	private short hour;
	private short minute;
	private short second;
	private short millisecond;

	/*
	 * GMT offset in minutes
	 */
	private short offset;

	private String str;

	/*
	 * ([0-9]{4})-([0-1]{1}[1-9]{1})-([0-3]{1}[0-9]{1})\\s([0-2]{1}[0-9]{1}):([0-
	 * 6]{1}[0-9]{1}):([0-6]{1}[0-9]{1}).([0-9]{3})\\s(\\+|-[0-2]{1}[0-9]{1})
	 */

	private static final Pattern pattern = Pattern
			.compile("([0-9]{4})-([0-1]?[0-9]{1})-([0-3]?[0-9]{1})\\s([0-2]?[0-9]{1}):([0-6]?[0-9]{1}):([0-6]?[0-9]{1})\\.([0-9]{1,3})\\s?([+-][0-2]?[0-9]{1})");

	/**
	 * 
	 */
	public TimeStampWithTimeZone(String value) {

		super();

		Matcher matcher = pattern.matcher(value);
		if (!matcher.matches()) {
			throw new IllegalArgumentException("date format (" + value + ") is not correct");
		}

		String year = matcher.group(1);
		log.debug("year = " + year);
		String month = matcher.group(2);
		log.debug("month = " + month);
		String day = matcher.group(3);
		log.debug("day = " + day);
		String hour = matcher.group(4);
		log.debug("hour = " + hour);
		String minute = matcher.group(5);
		log.debug("minute = " + minute);
		String second = matcher.group(6);
		log.debug("second = " + second);
		String millisecond = matcher.group(7);
		log.debug("millisecond = " + millisecond);
		String offset = matcher.group(8);
		log.debug("offset = " + offset);

		this.year = Short.parseShort(year);
		log.debug("year = " + this.year);
		this.month = Short.parseShort(month);
		log.debug("month = " + this.month);
		this.day = Short.parseShort(day);
		log.debug("day = " + this.day);
		this.hour = Short.parseShort(hour);
		log.debug("hour = " + this.hour);
		this.minute = Short.parseShort(minute);
		log.debug("minute = " + this.minute);
		this.second = Short.parseShort(second);
		log.debug("second = " + this.second);
		this.millisecond = Short.parseShort(millisecond);
		log.debug("millisecond = " + this.millisecond);
		this.offset = Short.parseShort(offset);
		log.debug("offset = " + this.offset);
	}

	public TimeStampWithTimeZone(long time, short offset) {
		Calendar calendar = new GregorianCalendar();
		year = (short) calendar.get(Calendar.YEAR);
		month = (short) calendar.get(Calendar.MONTH);
		day = (short) calendar.get(Calendar.DAY_OF_MONTH);
		hour = (short) calendar.get(Calendar.HOUR_OF_DAY);
		minute = (short) calendar.get(Calendar.MINUTE);
		second = (short) calendar.get(Calendar.SECOND);
		millisecond = (short) calendar.get(Calendar.MILLISECOND);
		this.offset = (short) offset;
	}

	public long getGMTTime() {
		Calendar calendar = new GregorianCalendar();
		calendar.set(year, month, day, hour, minute, second);
		calendar.set(Calendar.MILLISECOND, millisecond);
		calendar.add(Calendar.HOUR, -offset);
		return calendar.getTime().getTime();
	}

	public long getTime() {
		Calendar calendar = new GregorianCalendar();
		calendar.set(year, month, day, hour, minute, second);
		calendar.set(Calendar.MILLISECOND, millisecond);
		return calendar.getTime().getTime();
	}

	@Override
	public String toString() {
		if (str == null) {
			StringBuffer buf = new StringBuffer();
			buf.append(shortToStr(year, (short) 4));
			buf.append('-');
			buf.append(shortToStr(month, (short) 2));
			buf.append('-');
			buf.append(shortToStr(day, (short) 2));
			buf.append(' ');
			buf.append(shortToStr(hour, (short) 2));
			buf.append(':');
			buf.append(shortToStr(minute, (short) 2));
			buf.append(':');
			buf.append(shortToStr(second, (short) 2));
			buf.append('.');
			buf.append(shortToStr(millisecond, (short) 3));
			buf.append(' ');
			buf.append(shortToStr(offset, (short) 2));
			str = buf.toString();
		}
		return str;
	}

	public String shortToStr(short sh, short zeros) {
		boolean minus = sh < 0;
		if (sh < 0)
			sh = (short) -sh;
		String str = Short.toString(sh);
		for (int i = 0; i < zeros - str.length(); i++) {
			str = '0' + str;
		}
		if (minus)
			str = '-' + str;
		return str;
	}

	public static void main(String[] args) throws ParseException {
		
		TimeStampWithTimeZone tswtz = new TimeStampWithTimeZone("2012-08-16 16:26:33.78+05");
		Timestamp tmstmp = new Timestamp(tswtz.getGMTTime());
		System.out.println(tmstmp);
		tmstmp = new Timestamp(tswtz.getTime());
		System.out.println(tmstmp);
		System.out.println(TimeZone.getDefault().getOffset(new Date().getTime()) / (60 * 60 * 1000));

		/*
		 * long timeX = 0L; // 1 January, 1970 DateFormat df = new
		 * SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ss.SSS' 'X"); Random r = new
		 * Random(); long timeY =
		 * df.parse("1970-01-30 24:00:00.768 -03").getTime(); for(long i =
		 * timeX; i < timeY; i += 1){ new TimeStampWithTimeZone(df.format(new
		 * Date(i))); }
		 */

	}

}
